package com.yifeng.repo.base.encryption.conf;

import com.gomcarter.frameworks.base.exception.CustomException;
import com.google.common.base.Strings;
import com.yifeng.repo.base.constant.BaseConstant;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * Created by daibing on 2023/9/15.
 */
@Slf4j
public final class NacosConfManager {
    private static final Long ONE_HOUR_MILLIS = 60 * 60 * 1000L;
    private static final String BASE_APP_ID = "yfcloud-base";
    private static final String BASE_APP_VER = "1.0.0";
    private static final String AES_KEY = "encryption.aes-keys";
    private final ConcurrentMap<String, String> conf = new ConcurrentHashMap<>();
    private final URL url = buildUrl();
    private final AtomicLong lastRefreshTime = new AtomicLong(0L);

    public List<String> listAesKey() {
        refreshConf(ONE_HOUR_MILLIS);
        String property = conf.get(AES_KEY);
        if (Strings.isNullOrEmpty(property)) {
            return Collections.emptyList();
        }
        return Arrays.stream(property.split(BaseConstant.SEPARATOR)).collect(Collectors.toList());
    }

    private URL buildUrl() {
        String baseAppId = getValue("base_app_id", BASE_APP_ID);
        String baseAppVer = getValue("base_app_ver", BASE_APP_VER);
        String appStage = getValue("base_app_stage", "app_stage", null);
        String appConf = getValue("base_app_conf", "app_conf", null);
        String username = getValue("base_conf_username", "conf_username", null);
        String password = getValue("base_conf_password", "conf_password", null);
        String mapping = getValue("nacos.mapping", "/nacos/v1/cs/configs");
        try {
            String url = String.format("%s%s?dataId=%s&group=%s&tenant=%s&username=%s&password=%s",
                    appConf, mapping, baseAppId, baseAppVer, appStage, username, password);
            return new URL(url);
        } catch (MalformedURLException e) {
            throw new CustomException(e);
        }
    }

    private void refreshConf(Long intervalMillis) {
        if (lastRefreshTime.get() + intervalMillis > System.currentTimeMillis()) {
            return;
        }
        synchronized (conf) {
            if (lastRefreshTime.get() + intervalMillis > System.currentTimeMillis()) {
                return;
            }
            try {
                Properties properties = new Properties();
                properties.load(url.openStream());
                Map<String, String> map = properties.stringPropertyNames().stream().collect(Collectors.toMap(s -> s, properties::getProperty));
                conf.clear();
                conf.putAll(map);
                lastRefreshTime.set(System.currentTimeMillis());
            } catch (IOException e) {
                // 调用配置中心获取密钥失败，直接跳过。
                log.warn("获取密钥失败，error：", e);
            }
        }
    }

    private String getValue(String envKey, String defaultValue) {
        String envValue = System.getProperty(envKey);
        if (!Strings.isNullOrEmpty(envValue)) {
            return envValue;
        }
        envValue = System.getenv(envKey);
        if (!Strings.isNullOrEmpty(envValue)) {
            return envValue;
        }
        return defaultValue;
    }

    private String getValue(String envKey1, String envKey2, String defaultValue) {
        String envValue = System.getProperty(envKey1);
        if (!Strings.isNullOrEmpty(envValue)) {
            return envValue;
        }
        envValue = System.getenv(envKey1);
        if (!Strings.isNullOrEmpty(envValue)) {
            return envValue;
        }
        envValue = System.getProperty(envKey2);
        if (!Strings.isNullOrEmpty(envValue)) {
            return envValue;
        }
        envValue = System.getenv(envKey2);
        if (!Strings.isNullOrEmpty(envValue)) {
            return envValue;
        }
        return defaultValue;
    }
}
